package com.lkm.market2_0.m_imple.steelyarddata;

import android.os.Handler;
import android.support.annotation.Nullable;

import com.lkm.frame.P;
import com.lkm.frame.module.ModuleManager;
import com.lkm.frame.otto.LinkBus;
import com.lkm.frame.task2.Task;
import com.lkm.javatool.CollectionHelp;
import com.lkm.javatool.DateHelp;
import com.lkm.javatool.ServerTimeSync;
import com.lkm.javatool.StringHelp;
import com.lkm.javatool.lang.RunnablePR;
import com.lkm.market2_0.ExpandConfig;
import com.lkm.market2_0.TaskIdIndex;
import com.lkm.market2_0.entity.ResponEntity;
import com.lkm.market2_0.help.TaskHelp;
import com.lkm.market2_0.help.UIP;
import com.lkm.market2_0.entity.SteelyardInfo;
import com.lkm.market2_0.m.dataUp.DataUpFace;
import com.lkm.market2_0.m.steelyarddata.OrderEntity;
import com.lkm.market2_0.m.steelyarddata.SteelyardDataModule;
import com.lkm.market2_0.m.steelyarddata.SteelyardValue;
import com.lkm.market2_0.m.steelyardstatus.SteelyardStatusManagerModule;
import com.lkm.market2_0.m.steelyardserver.to.WeightChangeInfo;
import com.lkm.market2_0.m.steelyarddata.OnSteelardInfoLoadEvent;
import com.lkm.market2_0.m.steelyardserver.event.OnSubtotalEvent;
import com.lkm.market2_0.task.AsyncTask2;
import com.lkm.market2_0.task.DefaultTaskExecutor;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


public class SteelyardDataModuleImple implements SteelyardDataModule {

    private ModuleManager mModuleManager;

    private DataManager                  dataManager;
    private SteelyardStatusManagerModule mSteelyardStatusModule = null;


    private Map<String, SaleCacheInfo> deviceidSaleCacheInfoMap = new Hashtable<>();


    private Map<String, SteelyardInfo> steelyardInfoMap = new ConcurrentHashMap<>();

    private Map<String, SteelyardValue> steelyardValueMap = new ConcurrentHashMap<>();

    public SteelyardDataModuleImple(ModuleManager mModuleManager) {
        this.dataManager = new DataManager(this);

        this.mModuleManager = mModuleManager;

        RegBalanceTask.waitValue();

        loopUp();

    }

    private void loopUp() {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                if (!dataManager.isUpdateIng()) {
                    dataManager.updataData();
                }
                loopUp();
            }
        }, com.lkm.market2_0.m_imple.steelyardserver.server.Config.upSteelyardDataTime);
    }


    @Override
    public SteelyardInfo getSteelyardInfo(String steelyardMac) {
        if (steelyardMac == null) return null;
        return steelyardInfoMap.get(steelyardMac);
    }


    @Override
    public void regSteelyardInfo(SteelyardInfo steelyardInfo) {
        if (steelyardInfo != null) {
            steelyardInfoMap.put(steelyardInfo.getSteelyardMac(), steelyardInfo);

//            if(Config.instance.isUI()){

            OnSteelardInfoLoadEvent.send(steelyardInfo);


        }
    }

    @Override
    public void regSteelyardValue(SteelyardValue steelyardValue) {
        if (steelyardValue != null) {
            steelyardValueMap.put(steelyardValue.steelyardMac, steelyardValue);
        }

    }

    @Override
    public SteelyardValue getSteelyardValue(String steelyardMac) {
        if (steelyardMac == null) return null;
        return steelyardValueMap.get(steelyardMac);
    }


    @Override
    public void AD(String steelyardMac, int ad, int zeroAD, int offsetZeroAD, int kValue) {
        SaleCacheInfo saleCacheInfo = deviceidSaleCacheInfoMap.get(steelyardMac);

        if (saleCacheInfo != null) {
            synchronized (saleCacheInfo) {
                saleCacheInfo.upRealWeight(saleCacheInfo.tempWeight);
                saleCacheInfo.setAD(ad);
                saleCacheInfo.setZeroAD(zeroAD);
                saleCacheInfo.setOffsetZeroAD(offsetZeroAD);
                saleCacheInfo.setKvalue(kValue);
            }
        }
    }


    @Override
    public @Nullable
    List<OrderEntity.GoodEntity> getGoodEntities(String steelyardMac) {
        SaleCacheInfo saleCacheInfo = deviceidSaleCacheInfoMap.get(steelyardMac);
        if (saleCacheInfo != null) {
            return saleCacheInfo.getGoodEntities();
        }
        return null;
    }


    @Override
    public int removeGoodEntities(String steelyardMac, int index) {
        SaleCacheInfo saleCacheInfo = deviceidSaleCacheInfoMap.get(steelyardMac);
        if (saleCacheInfo != null) {
            return saleCacheInfo.removeGoodEntitie(index);
//            List<OrderEntity.GoodEntity> goodEntities = saleCacheInfo.getGoodEntities();


        }
        return 0;
    }

    @Override
    public void removeAllGoodEntities(String steelyardMac) {
        //P.d("Bill->removeAllGoodEntities:是不是被清了?");
        SaleCacheInfo saleCacheInfo = deviceidSaleCacheInfoMap.get(steelyardMac);
        if (saleCacheInfo != null)
            saleCacheInfo.removeAllGoodEntitie();
    }


    @Override
    public OrderEntity.GoodEntity regLastWeightChangeToOrderGood(String steelyardMac) {

        OrderEntity.GoodEntity goodEntity    = null;
        SaleCacheInfo          saleCacheInfo = deviceidSaleCacheInfoMap.get(steelyardMac);
        if (saleCacheInfo != null) {
            SteelyardInfo steelyardInfo = getSteelyardInfo(steelyardMac);
            if (steelyardInfo != null) {

                List<OrderEntity.GoodEntity> goodEntities = saleCacheInfo.getGoodEntities();
//                if (goodEntities != null)
//                    P.d("Bill->addGoodEntities:01:size:" + goodEntities.size());
//                else
//                    P.d("Bill->addGoodEntities:01:size:" + null);
                saleCacheInfo.addGoodEntitie(goodEntity = SaleCacheInfo.toGoodEntity(steelyardInfo, saleCacheInfo));
            }
        }
        return goodEntity;
    }


    @Override
    public OrderEntity.GoodEntity getCurWeightChangeGood(String steelyardMac) {
        OrderEntity.GoodEntity goodEntity    = null;
        SaleCacheInfo          saleCacheInfo = deviceidSaleCacheInfoMap.get(steelyardMac);
        if (saleCacheInfo != null) {
            SteelyardInfo steelyardInfo = getSteelyardInfo(steelyardMac);
            if (steelyardInfo != null)
                goodEntity = SaleCacheInfo.toGoodEntity(steelyardInfo, saleCacheInfo);
        }
        return goodEntity;
    }

    @Override
    public boolean subtotal(String steelyardMac, OrderEntity.GoodEntity goodEntity) {
        SaleCacheInfo saleCacheInfo = deviceidSaleCacheInfoMap.get(steelyardMac);
        if (saleCacheInfo != null) {
            //P.d("Bill->addGoodEntities:02:");
            saleCacheInfo.addGoodEntitie(goodEntity);

            if (ExpandConfig.instance.isUI()) {

                if (goodEntity != null)
                    LinkBus.sendBroadcast(new OnSubtotalEvent(steelyardMac, goodEntity));
            }
            return true;
        }
        return false;
    }


    @Deprecated
    public void saveLastWeightChangeToOrderEntity(String steelyardMac) {

        SaleCacheInfo saleCacheInfo = deviceidSaleCacheInfoMap.remove(steelyardMac);
        if (saleCacheInfo != null && saleCacheInfo.getWeight() != 0) {

            save(steelyardMac, saleCacheInfo, null);
        }
    }


    @Override
    public void weightChange(String steelyardMac, WeightChangeInfo weightChangeInfo) {


        tryReplaceCurName(weightChangeInfo);

        String goodsId   = "";
        String goodName  = weightChangeInfo.getName();
        float  unitPrice = weightChangeInfo.getUnitPrice();
        float  weight    = weightChangeInfo.getWeight();
        String date      = weightChangeInfo.getDate();


        SaleCacheInfo saleCacheInfo = deviceidSaleCacheInfoMap.get(steelyardMac);

        if (saleCacheInfo == null) {
            saleCacheInfo = new SaleCacheInfo(goodsId, goodName, unitPrice, weight, date, weightChangeInfo.isUseThisDate, weightChangeInfo.getUnitType(), weightChangeInfo.isSalesReturn(), weightChangeInfo.isHistory());
            deviceidSaleCacheInfoMap.put(steelyardMac, saleCacheInfo);
        }


        if ((weightChangeInfo.getUnitType() == 1 && weight == 0 && CollectionHelp.isEmpty(saleCacheInfo.getGoodEntities()) && !ExpandConfig.instance.isUI())) {


            saveLastWeightChangeToOrderEntity(steelyardMac);

        } else {

            saleCacheInfo.update(goodsId, goodName, unitPrice, weight, date, weightChangeInfo.isUseThisDate, weightChangeInfo.getUnitType(), weightChangeInfo.isSalesReturn(), weightChangeInfo.isHistory());
        }
    }

    @Override
    public OrderEntity print(String steelyardMac, boolean isSalesJoin) {
        SaleCacheInfo saleCacheInfo = deviceidSaleCacheInfoMap.get(steelyardMac);

        OrderEntity orderEntity = null;

        if (saleCacheInfo != null) {
            try {
//                saleCacheInfo.setLockSaleCacheInfo((SaleCacheInfo) saleCacheInfo.clone());
                SaleCacheInfo lockSaleCacheInfo = (SaleCacheInfo) saleCacheInfo.clone();
                deviceidSaleCacheInfoMap.remove(steelyardMac);
                lockSaleCacheInfo.setSalesJoin(isSalesJoin);

                orderEntity = save(steelyardMac, saleCacheInfo, lockSaleCacheInfo);
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
        }
        return orderEntity;
    }


    @Override
    public OrderEntity onlyCreateOrderEntity(String steelyardMac, RunnablePR<String, String> orderHanler) {
        SaleCacheInfo saleCacheInfo = deviceidSaleCacheInfoMap.get(steelyardMac);
        OrderEntity   orderEntity   = null;

        if (saleCacheInfo != null) {
            try {

                SaleCacheInfo lockSaleCacheInfo = (SaleCacheInfo) saleCacheInfo.clone();
                SteelyardInfo steelyardInfo     = getSteelyardInfo(steelyardMac);

                orderEntity = createOrderEntity(steelyardInfo, saleCacheInfo, lockSaleCacheInfo, orderHanler);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return orderEntity;
    }


    private @Nullable
    OrderEntity createOrderEntity(SteelyardInfo steelyardInfo, SaleCacheInfo saleCacheInfo, SaleCacheInfo lockSaleCacheInfo, RunnablePR<String, String> orderHanler) {
        if (steelyardInfo == null) {


            return null;
        }
        String steelyardMac = steelyardInfo.getSteelyardMac();

        SaleCacheInfo saveSaleCacheInfo = saleCacheInfo;

        boolean isClickPrint = lockSaleCacheInfo != null;
        boolean isFullOrder  = isClickPrint;

        if (isClickPrint) {
            saveSaleCacheInfo = lockSaleCacheInfo;
        }

        synchronized (saveSaleCacheInfo) {

            List<OrderEntity.GoodEntity> goodEntities = saveSaleCacheInfo.getGoodEntities();

            if (goodEntities == null) {

                goodEntities = new ArrayList<>();

                OrderEntity.GoodEntity goodEntity = SaleCacheInfo.toGoodEntity(steelyardInfo, saveSaleCacheInfo);
                goodEntities.add(goodEntity);
            } else {

                goodEntities = new ArrayList<>(goodEntities);
            }


            String createTime = saveSaleCacheInfo.isUseThisDate ? saveSaleCacheInfo.getDate() :


                    DateHelp.DateFormatyyyy_MM_dd_HHmmss(Locale.getDefault()).format(ServerTimeSync.getInstance().getServerCurTime());


            String orderNum = CreateOrderNum.callorderNum(isFullOrder, saveSaleCacheInfo, steelyardInfo);


            int type = isFullOrder ? OrderEntity.TYPE_Full1 : OrderEntity.TYPE_NotFull0;
            if (saveSaleCacheInfo.isSalesReturn())
                type = OrderEntity.TYPE_SalesReturn2;

            if (saveSaleCacheInfo.isHistory())
                type = OrderEntity.TYPE_History3;
            if (saveSaleCacheInfo.isSalesJoin())
                type = OrderEntity.TYPE_SalesJoin4;


            if (orderHanler != null) {
                orderNum = orderHanler.run(orderNum);
            }
            OrderEntity orderEntity = OrderEntity.createOrderEntity(steelyardMac, type, createTime, goodEntities, orderNum);

            return orderEntity;

        }
    }


    @Override
    public void saveOrderEntity(String steelyardMac, OrderEntity orderEntity) {
        SteelyardInfo steelyardInfo = getSteelyardInfo(steelyardMac);

        if (P.isDebug()) {
            P.p("=====保存订单" + steelyardMac);
        }
        if (orderEntity != null)
            dataManager.putData(steelyardMac, orderEntity);
        if (orderEntity != null && steelyardInfo != null) {
            DataUpFace.submitWeightInfo(steelyardInfo, orderEntity);
        }

    }


    private @Nullable
    OrderEntity save(String steelyardMac, SaleCacheInfo saleCacheInfo, SaleCacheInfo lockSaleCacheInfo) {
        SteelyardInfo steelyardInfo = getSteelyardInfo(steelyardMac);

        if (P.isDebug()) {
            P.p("=====保存订单" + steelyardMac);
        }

        OrderEntity orderEntity = createOrderEntity(steelyardInfo, saleCacheInfo, lockSaleCacheInfo, null);

        if (orderEntity != null)
            dataManager.putData(steelyardMac, orderEntity);


        if (orderEntity != null && steelyardInfo != null) {
            DataUpFace.submitWeightInfo(steelyardInfo, orderEntity);
        }


        return orderEntity;
    }

    @Override
    public void steelyardHeartbeatCollect(String steelyardMac, long time, boolean isExceptions, String version, String steelyardNumno, float voltage) {


//                if (Config.instance.getTaskManager2().getRunTask("loadBreedForSTask" + steelyardMac) == null) {


        if (mSteelyardStatusModule == null) {

            mSteelyardStatusModule = mModuleManager.loadModule(SteelyardStatusManagerModule.class);
        }
        if (mSteelyardStatusModule != null) {

            mSteelyardStatusModule.receiver(steelyardMac, time, isExceptions, version, steelyardNumno, voltage);
        }

    }


    @Override
    public Task<String, String, ResponEntity<SteelyardInfo>> LoadSteelyardInfoForS(final String steelyardMac) {

        String taskId = TaskIdIndex.loadSteelyardInfoTaskId(steelyardMac);

        Task<String, String, ResponEntity<SteelyardInfo>> task = TaskHelp.getTask(taskId);

        if (task != null && task.getIsContinue()) {
            if (P.isDebug()) {
                P.p("====加载台秤初始化数据 已经有在加载中的了" + steelyardMac);
                if (UIP.isPrint()) {
                    UIP.p("加载台秤初始化数据 已经有在加载中的了", steelyardMac);
                }
            }
            return task;
        }

        if (P.isDebug()) {
            P.p("====加载台秤初始化数据 " + steelyardMac);
            if (UIP.isPrint()) {
                UIP.p("加载台秤初始化数据 ", steelyardMac);
            }
        }

        LoadSteelyardInfoTask loadSteelyardInfoTask = new LoadSteelyardInfoTask(new DefaultTaskExecutor<String, String, ResponEntity<SteelyardInfo>>(true), ExpandConfig.instance.getTaskManager2(), taskId) {
            @Override
            public void onFinish(ResponEntity<SteelyardInfo> re) {
                super.onFinish(re);
                if (P.isDebug()) {
                    P.p("====加载台秤初始化数据 成功? " + re.isSuccess() + steelyardMac);
                    if (UIP.isPrint()) {
                        UIP.p("加载台秤初始化数据 成功? " + re.isSuccess(), steelyardMac);
                    }
                }
                if (re.isSuccess()) {

                    if (re.getData() != null) {
                        regSteelyardInfo(re.getData());//.put(steelyardMac, re.getData());

//                        syncGoodsButtonToSteelyard(steelyardMac, re.getData().getBreedTo());
                    } else {


                    }
                }
            }
        };
        loadSteelyardInfoTask.setId(taskId);
        loadSteelyardInfoTask.action();
        loadSteelyardInfoTask.setParam(steelyardMac);
        loadSteelyardInfoTask.execTask();
        return loadSteelyardInfoTask;
    }

    @Override
    public void clearSaleCacheInfo(String steelyardMac) {
        deviceidSaleCacheInfoMap.remove(steelyardMac);
    }


    String needReplaceName;
    String replaceName;


    String lastReadName;

    @Override
    public synchronized void replaceCurName(String goodsName) {
        needReplaceName = lastReadName;
        replaceName = goodsName;

    }

    public void tryReplaceCurName(WeightChangeInfo curWeightChangeInfo) {
        try {
            lastReadName = curWeightChangeInfo.getName();
            if (curWeightChangeInfo.getName().equals(needReplaceName)) {

                curWeightChangeInfo.setName(replaceName);
            } else if (!StringHelp.equals(replaceName, curWeightChangeInfo.getName())) {

                needReplaceName = null;
                replaceName = null;
            }
        } catch (Exception e) {
        }

    }
}
